import { createApp, ref, toRef, markRaw } from 'vue'
import App from './App.vue'
import router from './router/index'

import { createPinia } from 'pinia'
// 方式二
// 为安装此插件后创建的每个 store 添加一个名为 secret 的属性
function secretPiniaPlugin() {
  return { secret: 'the cake is a lie' }
}
const pinia = createPinia()
// 将插件提供给 pinia
// pinia.use(secretPiniaPlugin)

// 扩充store：可以通过简单地在插件中返回它们的对象来为每个 store 添加属性
// 插件的任何属性 returned 都会被devtools自动跟踪
// pinia.use(() => ({ hello: 'world' }))


// pinia.use(({ store }) => {
//   // store.hello = 'world'
//   store.hello = ref('world') // 每个 store 都使用 reactive 包装，自动展开任何 Ref
//   // 所以为了让hello在devtools中可见，如果你想调试它，请确保将它添加到store._customProperties仅在开发模式 开发工具
//   // 确保您的打包器可以处理这个问题。 webpack 和 vite 应该默认这样做
//   if (process.env.NODE_ENV === 'development') {
//     // 添加您在 store 中设置的任何 keys
//     store._customProperties.add('hello')
//   }
// })
// 上面的3种方式都是添加到每个store的 customProperties 上



// 添加新状态，如果想将新的状态属性添加到 store 或打算在 hydration 中使用的属性，必须同时在两个地方添加它：第一在store上添加，这样可以使用store.newState访问；第二在store.$state上添加，这样可以在devtools 中使用，并且在 SSR 期间被序列化
// 直接将新状态添加到每个store的 state 上
const globalSecret = ref('secret')
pinia.use(({ store }) => {
  // secret 在所有 store 之间共享
  store.$state.secret = globalSecret
  store.secret = globalSecret // 它会自动展开 secret

  const hello = ref(false)
  store.$state.hello = hello
  // 这个必须设置
  store.hello = toRef(store.$state, 'hello')
  
  // 在这种情况下，最好不要返回 hello，因为它将显示在 devtools 的 state部分。如果我们返回它，将在 devtools 显示两次它

  // 注意：插件中发生的状态更改或添加（包括调用store.$patch()）发生在存储处于活动状态之前，因此不会触发任何订阅。
  // store.count++
})


// 添加新的外部属性：当添加外部属性，来自其他库的类实例或仅仅是非响应式的东西时，你应该在将对象传递给 pinia 之前使用 markRaw() 包装对象
pinia.use(({ store }) => {
  // 将路由添加到每个 store 的示例
  store.router = markRaw(router)

  // 也可以在插件中使用 $subscribe 额 $onAction
  store.$subscribe(() => {
    // 在存储变化的时候执行
    console.log('subscribe')
  })
  store.$onAction(() => {
    // 在 action 的时候执行
    console.log('onAction')
  })
})


// 组件全局注册
import Child from './components/Child.vue'
// 使用 PascalCase 作为组件名的注册格式

import i18nPlugin from './plugins/i18n'

createApp(App)
  .component('ChildA', Child)
  // 全局自定义指令：此处注意调用时机是在 mount('#app) 之前，否则指令都未挂载到实例上导致报错
  .directive('comp', {
    mounted: () => {
      console.log('我是全局自定义指令')
    }
  })
  // 使用插件，此处的插件希望用户在使用该插件时通过选项传入一个翻译字典对象
  .use(i18nPlugin, {
    greetings: {
      hello: 'Bonjour!'
    }
  })
  .use(router)
  // .use(createPinia()) // 方式一：注意这里有括号
  .use(pinia) // 方式二
  .mount('#app')